﻿using System;
using System.Data;
using System.Configuration;

using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections;
using System.Collections.Generic;

namespace TA.Turbo
{
	/// <summary>
	/// Include content which is cached on the server for subsequent requests to the same content.
	/// </summary>
	public class CombinedContent
	{
		#region STATIC
		/// <summary>
		/// Gets a hashtable of keys and corresponding <see cref="CombinedContent"/> objects for retrieving include content.
		/// </summary>
		public static Dictionary<long, CombinedContent> CachedContent
		{
			get
			{

				if (!(HttpContext.Current.Application[CachedContentKey] is Dictionary<long, CombinedContent>))
					HttpContext.Current.Application[CachedContentKey] = new Dictionary<long, CombinedContent>();
				return (Dictionary<long, CombinedContent>)HttpContext.Current.Application[CachedContentKey];
			}
		}
		/// <summary>
		/// Gets a hashtable of text lengths and corresponding <see cref="CombinedContent"/> objects for effective prevention of duplicates.
		/// </summary>
		public static Dictionary<int, List<CombinedContent>> CachedContentByTextLength
		{
			get
			{
				string k = CachedContentKey + "ByText";
				if (!(HttpContext.Current.Application[k] is Dictionary<int, List<CombinedContent>>))
					HttpContext.Current.Application[k] = new Dictionary<int, List<CombinedContent>>();
				return (Dictionary<int, List<CombinedContent>>)HttpContext.Current.Application[k];
			}
		}
		/// <summary>
		/// Tries to retrieve an existing <see cref="CombinedContent"/> and if it doesn't exist, creates a new one.
		/// </summary>
		/// <param name="text"></param>
		/// <param name="contentType"></param>
		/// <returns></returns>
		public static CombinedContent Get(string text, string contentType)
		{
			List<CombinedContent> ccs;
			if (CachedContentByTextLength.TryGetValue(text.Length, out ccs))
			{
				foreach (CombinedContent cc in ccs)
				{
					if (string.Equals(cc.Text, text))
						return cc;
				}
			}
			return new CombinedContent(text, contentType);
		}
		#endregion
		#region PUBLIC
		#region INIT
		/// <summary>
		/// Ctor.
		/// </summary>
		/// <param name="text"></param>
		/// <param name="contentType"></param>
		public CombinedContent(string text, string contentType)
		{

			_key = (long)rnd.Next(1000000, 9999999) * 10000000 + (long)rnd.Next(1000000, 9999999);
			this.Text = text;
			this.ContentType = contentType;

			CachedContent[_key] = this;
			if (!CachedContentByTextLength.ContainsKey(text.Length))
			{
				CachedContentByTextLength[text.Length] = new List<CombinedContent>();
			}
			CachedContentByTextLength[text.Length].Add(this);
		}
		#endregion
		#region PROPS
		/// <summary>
		/// The key of this content, passed in the query string.
		/// </summary>
		public long Key
		{
			get { return _key; }
		}
		/// <summary>
		/// MIME-type of the content.
		/// </summary>
		public string ContentType { get; set; }
		/// <summary>
		/// The text content.
		/// </summary>
		public string Text { get; set; }
		#endregion
		#region METHODS
		/// <summary>
		/// Returns true if this combined content contains the specified text.
		/// </summary>
		/// <param name="text"></param>
		/// <returns></returns>
		public bool Has(string text)
		{
			return string.Equals(Text, text);
		}
		#endregion
		#endregion
		#region INTERNAL
		#region CONST/STATIC
		static readonly Random rnd = new Random();
		const string CachedContentKey = "TA.Turbo";
		#endregion
		#region VARS
		long _key;
		//string _content;
		#endregion
		#region METHODS
		#endregion
		#endregion
	}
}